package logic

import (
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"svvenus/conf"
	"svvenus/util/uttype"
	"svvenus/vgame/model"
	"svvenus/vpub/constants"
	"svvenus/vpub/db/dbm"
	"svvenus/zlog"
	"svvenus/znet/zpb"
	"time"
)

// Mail
// @Description: 邮件
type Mail struct {
	model.MailDoc
	IsNew    bool `bson:"-"` //是否新的
	NeedSave bool `bson:"-"` //是否需要存档
}

func NewMail() *Mail {
	mail := new(Mail)
	mail.Awards = make([]conf.PcAward, 0)
	mail.Got = true
	return mail
}

// Save
// @Description: 存档
// @receiver mail
// @param db
func (mail *Mail) Save(db *dbm.MgoSession) {
	if !(mail.IsNew || mail.NeedSave) {
		return
	}
	err := db.Save(&mail.MailDoc, mail.IsNew)
	if err != nil {
		zlog.Error(err)
	} else {
		mail.IsNew = false
		mail.NeedSave = false
	}
}

// Load
// @Description: 读档
// @receiver mail
// @param db
// @return bool
func (mail *Mail) Load(db *dbm.MgoSession) bool {
	err := db.GetId(&mail.MailDoc)
	if err != nil {
		zlog.Error(fmt.Sprintf("邮件读档失败 pid=%s id=%s", mail.Pid, mail.IdString()), err)
		return false
	}
	return true
}

// AddAward
// @Description: 添加附件
// @receiver mail
// @param award
func (mail *Mail) AddAward(award conf.PcAward) {
	mail.AddAwards([]conf.PcAward{award})
}

// AddAwards
// @Description: 添加附件
// @receiver mail
// @param awards
func (mail *Mail) AddAwards(awards []conf.PcAward) {
	for _, v := range awards {
		mail.Awards = append(mail.Awards, v)
	}
	mail.Got = false
}

// MailAddToPlayer
// @Description: 玩家添加邮件
// @receiver player
// @param mail
func (player *Player) MailAddToPlayer(mail *Mail) {
	mail.Id = bson.NewObjectId()
	mail.IsNew = true
	mail.NeedSave = true
	mail.Pid = player.IdString()
	player.MailIds = append(player.MailIds, mail.IdString())
	player.Mails[mail.IdString()] = mail

	player.MailAddData(mail)

	for len(player.MailIds) > conf.V玩家邮件最大数量 && len(player.MailIds) > 2 {
		idDel := player.MailIds[0]
		go player.MailDelData(idDel)
		delete(player.Mails, idDel)
		player.MailIds = player.MailIds[1:]
	}
}

// GlobalMailAddToPlayer
// @Description: 玩家添加全服邮件
// @receiver player
// @param gmail
func (player *Player) GlobalMailAddToPlayer(gmail *model.GlobalMailDoc) {
	mail := NewMail()
	mail.Title = gmail.Title
	mail.Body = gmail.Body
	mail.SenderName = "管理员"
	mail.CreateTime = time.Now()
	for idx, _ := range gmail.Awards {
		mail.AddAward(gmail.Awards[idx])
	}
	mail.MailType = int32(zpb.MailType_MailTypeGmGlobal)
	mail.RecSource = int32(zpb.RecSource_rsGm)
	player.MailAddToPlayer(mail)
}

// MailAddData
// @Description: 数据库添加
// @receiver player
// @param mail
func (player *Player) MailAddData(mail *Mail) {
	db := constants.MgoMain.New()
	defer db.Close()
	mail.Save(db)
}

// MailDelData
// @Description: 数据库删除
// @receiver player
// @param mail
func (player *Player) MailDelData(mailId string) {
	db := constants.MgoMain.New()
	defer db.Close()
	_ = db.RemoveId(model.MailCollectionName, bson.ObjectIdHex(mailId))
}

// MailInfo
// @Description: 邮件信息
// @receiver mail
// @return *zpb.MailInfo
func (mail *Mail) MailInfo() *zpb.MailInfo {
	info := &zpb.MailInfo{}
	info.Id = mail.IdString()
	info.MailType = (zpb.MailType)(mail.MailType)
	info.Title = mail.Title
	info.Body = mail.Body
	info.SenderName = mail.SenderName
	info.CreateTime = mail.CreateTime.String()
	info.Read = mail.Read
	info.Got = mail.Got
	info.Awards = make([]*zpb.PbAward, 0)
	for _, v := range mail.Awards {
		info.Awards = append(info.Awards, PcAward2PbAward(v))
	}
	return info
}

// MailInfoList
// @Description: 邮件信息列表
// @receiver player
// @return *zpb.MailInfoList
func (player *Player) MailInfoList() *zpb.MailInfoList {
	info := &zpb.MailInfoList{}
	info.Mails = make([]*zpb.MailInfo, 0)
	for _, v := range player.Mails {
		info.Mails = append(info.Mails, v.MailInfo())
	}
	return info
}

// MailCheckOverdue
// @Description: 清理过期邮件
// @receiver player
func (player *Player) MailCheckOverdue() {
	listDelete := make([]string, 0)
	for _, v := range player.Mails {
		dayCount := conf.V玩家未读邮件有效时间
		if v.Read && v.Got {
			dayCount = conf.V玩家已读邮件有效时间
		}
		if constants.SvTime.After(v.CreateTime.Add(time.Hour * 24 * time.Duration(dayCount))) {
			listDelete = append(listDelete, v.IdString())
		}
	}
	for _, v := range listDelete {
		delete(player.Mails, v)
		go player.MailDelData(v)
	}
	player.MailIds = uttype.SliceStringDelItems(player.MailIds, listDelete)
}
